package com.mini.mybatis.session.defaults;

import com.mini.mybatis.executor.Executor;
import com.mini.mybatis.mapping.MappedStatement;
import com.mini.mybatis.session.Configuration;
import com.mini.mybatis.session.SqlSession;

import java.io.IOException;
import java.sql.SQLException;
import java.util.List;

/**
 * 默认SqlSession实现
 */
public class DefaultSqlSession implements SqlSession {
    
    private final Configuration configuration;
    private final Executor executor;
    private final boolean autoCommit;
    private boolean dirty;
    private boolean closed;
    
    public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
        this.configuration = configuration;
        this.executor = executor;
        this.autoCommit = autoCommit;
        this.dirty = false;
        this.closed = false;
    }
    
    @Override
    public <T> T selectOne(String statement) {
        return this.selectOne(statement, null);
    }
    
    @Override
    public <T> T selectOne(String statement, Object parameter) {
        List<T> list = this.selectList(statement, parameter);
        if (list.size() == 1) {
            return list.get(0);
        } else if (list.size() > 1) {
            throw new RuntimeException("期望查询一个结果，但实际返回了 " + list.size() + " 个结果");
        } else {
            return null;
        }
    }
    
    @Override
    public <E> List<E> selectList(String statement) {
        return this.selectList(statement, null);
    }
    
    @Override
    public <E> List<E> selectList(String statement, Object parameter) {
        try {
            MappedStatement ms = configuration.getMappedStatement(statement);
            return executor.query(ms, wrapCollection(parameter));
        } catch (Exception e) {
            throw new RuntimeException("查询操作失败。语句ID: " + statement + "。原因: " + e, e);
        }
    }
    
    @Override
    public int insert(String statement) {
        return insert(statement, null);
    }
    
    @Override
    public int insert(String statement, Object parameter) {
        return update(statement, parameter);
    }
    
    @Override
    public int update(String statement) {
        return update(statement, null);
    }
    
    @Override
    public int update(String statement, Object parameter) {
        try {
            dirty = true;
            MappedStatement ms = configuration.getMappedStatement(statement);
            return executor.update(ms, wrapCollection(parameter));
        } catch (Exception e) {
            throw new RuntimeException("更新操作失败。语句ID: " + statement + "。原因: " + e, e);
        }
    }
    
    @Override
    public int delete(String statement) {
        return update(statement, null);
    }
    
    @Override
    public int delete(String statement, Object parameter) {
        return update(statement, parameter);
    }
    
    @Override
    public void commit() {
        commit(false);
    }
    
    @Override
    public void rollback() {
        rollback(false);
    }
    
    @Override
    public void clearCache() {
        executor.clearLocalCache();
    }
    
    @Override
    public <T> T getMapper(Class<T> type) {
        return configuration.getMapper(type, this);
    }
    
    @Override
    public Configuration getConfiguration() {
        return configuration;
    }
    
    @Override
    public void close() throws IOException {
        try {
            executor.close(isCommitOrRollbackRequired(false));
            closeCursors();
            dirty = false;
        } finally {
            closed = true;
        }
    }
    
    /**
     * 提交事务
     */
    private void commit(boolean force) {
        try {
            executor.commit(isCommitOrRollbackRequired(force));
            dirty = false;
        } catch (SQLException e) {
            throw new RuntimeException("提交事务失败。原因: " + e, e);
        }
    }
    
    /**
     * 回滚事务
     */
    private void rollback(boolean force) {
        try {
            executor.rollback(isCommitOrRollbackRequired(force));
            dirty = false;
        } catch (SQLException e) {
            throw new RuntimeException("回滚事务失败。原因: " + e, e);
        }
    }
    
    /**
     * 关闭游标
     */
    private void closeCursors() {
        // 简化实现，暂不处理游标
    }
    
    /**
     * 判断是否需要提交或回滚
     */
    private boolean isCommitOrRollbackRequired(boolean force) {
        return (!autoCommit && dirty) || force;
    }
    
    /**
     * 包装集合参数
     */
    private Object wrapCollection(final Object object) {
        return ParamNameResolver.wrapToMapIfCollection(object, null);
    }
    
    /**
     * 简化版参数名解析器
     */
    private static class ParamNameResolver {
        public static Object wrapToMapIfCollection(Object object, String actualParamName) {
            // 简化实现，直接返回原对象
            return object;
        }
    }
}